#include "pcf8523.h"
#include "wiringPiI2C.h"

DateTime::DateTime()
{
	y = 2000;
	m = d = w = 1;
	hour = min = sec = 0;
}
DateTime::DateTime(int _y,int _m,int _d,int _hour,int _min,int _sec):
	y(_y),m(_m),d(_d),w(0),hour(_hour),min(_min),sec(_sec)
{

}	
DateTime::~DateTime()
{
}

DateTime::DateTime(const DateTime& dt)
{
		y = dt.y;
		m = dt.m;
		d = dt.d;
		w = dt.w;
		hour = dt.hour;
		min = dt.min;
		sec = dt.sec;
}

int DateTime::Year()
{
	return y;
}
int DateTime::Month()
{
	return m;
}
int DateTime::Day()
{
	return d;
}
int DateTime::Week()
{
	return w;
}
int DateTime::Hour()
{
	return hour;
}
int DateTime::Minute()
{
	return min;
}
int DateTime::Second()
{
	return sec;
}

ostream& operator<<(ostream & out,DateTime & dt)
{
		out << dt.y << "-" << dt.m << "-" << dt.d << " " << dt.hour << ":" << dt.min << ":" << dt.sec;
		return out;
}

DateTime& DateTime::operator=(const DateTime & dt)
{
		if(this != &dt)
		{
				y = dt.y;
				m = dt.m;
				d = dt.d;
				w = dt.w;
				hour = dt.hour;
				min = dt.min;
				sec = dt.sec;
		}
		return *this;
}

/*==================================================*/
static int bcd2bin(int val)
{
	return (val - 6*(val>>4));
}
static int bin2bcd(int val)
{
	return (val + 6*(val/10));
}

PCF8523::PCF8523(int addr):mI2cAddr(addr)
{
	mFd = wiringPiI2CSetup(addr);
}

PCF8523::~PCF8523()
{
	if(mFd >  0)
	{
		close(mFd);
		mFd = -1;
	}
}

DateTime PCF8523::now()
{
	return readTime();
}
DateTime PCF8523::readTime()
{
	int sec = wiringPiI2CReadReg8(mFd,RTC_REG_SEC);
	int min = wiringPiI2CReadReg8(mFd,RTC_REG_MIN);
	int hour = wiringPiI2CReadReg8(mFd,RTC_REG_HOUR);
	int day = wiringPiI2CReadReg8(mFd,RTC_REG_DAY);
	int mon = wiringPiI2CReadReg8(mFd,RTC_REG_MON);
	int year = wiringPiI2CReadReg8(mFd,RTC_REG_YEAR);

	int y = bcd2bin(year) + 2000;
	int m = bcd2bin(mon);
	int d = bcd2bin(day);
	int h = bcd2bin(hour);
	int mi = bcd2bin(min);
	int s = bcd2bin(sec&0x7f);
	return DateTime(y,m,d,h,mi,s);
}
void PCF8523::setTime(DateTime& dt)
{
	int y = bin2bcd(dt.Year() - 2000);
	int m = bin2bcd(dt.Month());
	int d = bin2bcd(dt.Day());
	int h = bin2bcd(dt.Hour());
	int mi = bin2bcd(dt.Month());
	int s = bin2bcd(dt.Second());

	wiringPiI2CWriteReg8(mFd,RTC_REG_SEC,s);
	wiringPiI2CWriteReg8(mFd,RTC_REG_SEC,mi);
	wiringPiI2CWriteReg8(mFd,RTC_REG_SEC,h);
	wiringPiI2CWriteReg8(mFd,RTC_REG_SEC,d);
	wiringPiI2CWriteReg8(mFd,RTC_REG_SEC,m);
	wiringPiI2CWriteReg8(mFd,RTC_REG_SEC,y);
}
void PCF8523::setTime(int y,int m,int d,int hour,int min,int sec)
{
	DateTime dt(y,m,d,hour,min,sec);
	setTime(dt);
}

void PCF8523::printTime(DateTime& dt)
{
	printf("PCF8523::RTC %04d-%02d-%02d %02d:%02d:%02d\n",
			dt.Year(),
			dt.Month(),
			dt.Day(),
			dt.Hour(),
			dt.Minute(),
			dt.Second()
	      );
}

bool PCF8523::isRunning()
{
	int val = wiringPiI2CReadReg8(mFd,0x00);
	int status = (val&32);

	if((status>>5)==1)
	{
		return true;
	}
	return false;
}

void PCF8523::setDefault()
{
	DateTime dt(2017,12,26,10,0,0);
	setTime(dt);
}



